
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/queue.h"
#include "esp_system.h"
#include "esp_log.h"
#include "esp_err.h"

#include "esp_spi_flash.h"
#include "driver/gpio.h"
#include "driver/uart.h"
#include "driver/spi.h"

#include "my_uart.h"
#include "my_spi.h"
#include "max7219.h"

static const char *TAG = "max7219 demo";

#define GPIO_PIN_LED 2
#define GPIO_OUTPUT_PIN (1UL << GPIO_PIN_LED)

uint8_t h = 21, m = 46, s = 1;

void Gpio_Init(void)
{
    gpio_config_t IO_config;

    IO_config.pin_bit_mask = GPIO_OUTPUT_PIN;
    IO_config.mode = GPIO_MODE_OUTPUT;
    IO_config.pull_up_en = GPIO_PULLUP_DISABLE;
    IO_config.pull_down_en = GPIO_PULLDOWN_DISABLE;
    IO_config.intr_type = GPIO_INTR_DISABLE;

    gpio_config(&IO_config);
    gpio_set_level(GPIO_PIN_LED,1);
}

void get_system_info(void)
{
    ESP_LOGI(TAG,"\nhello world\n");
    //获取IDF版本
    ESP_LOGI(TAG,"SDK version:%s\n", esp_get_idf_version());

    //获取芯片可用内存
    ESP_LOGI(TAG,"esp_get_free_heap_size : %d  \n", esp_get_free_heap_size());
    //获取从未使用过的最小内存
    ESP_LOGI(TAG,"esp_get_minimum_free_heap_size : %d  \n", esp_get_minimum_free_heap_size());
    //获取芯片的内存分布，返回值具体见结构体 flash_size_map
    ESP_LOGI(TAG,"system_get_flash_size_map(): %d \n", system_get_flash_size_map());
    //获取mac地址（station模式）
    uint8_t mac[6];
    esp_read_mac(mac, ESP_MAC_WIFI_STA);
    ESP_LOGI(TAG,"esp_read_mac(): %02x:%02x:%02x:%02x:%02x:%02x \n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);

    /* Print chip information */
    esp_chip_info_t chip_info;
    esp_chip_info(&chip_info);
    ESP_LOGI(TAG,"This is ESP8266 chip with %d CPU cores, WiFi, ",
        chip_info.cores);
    ESP_LOGI(TAG,"silicon revision %d, ", chip_info.revision);
    ESP_LOGI(TAG,"%dMB %s flash\n", spi_flash_get_chip_size() / (1024 * 1024),
        (chip_info.features & CHIP_FEATURE_EMB_FLASH) ? "embedded" : "external");
}

void uart_recv_task(void *argv)
{
    uint8_t *buf = calloc(1024,1);
    int len = 0;
    while (1)
    {
        my_uart_recv_data(UART_NUM_0,buf,&len);
        if(len > 0){
            buf[len] = 0;
            ESP_LOGW(TAG,"RX:%s",buf);
        }
    }
}

void MAX7219_Write_Data(uint8_t *data, uint16_t len)
{
    my_spi_write(data, len);
}

void write_time(uint8_t h, uint8_t m, uint8_t s)
{
    char buf[10] = {};
    uint8_t x = 1, y = 0;
    
    snprintf(buf, sizeof(buf), "%02d:%02d", h, m);

    for (size_t i = 0; i < strlen(buf); i++)
    {
        write_char_to_buf(x, y, buf[i], SIZE_F6X8);
        x += 6;
    }
    LedRefresh();
}

void refresh_task(void *argv)
{
    uint8_t s_old = 0;

    while (1)
    {
        if (s_old != s){
            write_time(h, m, s);
            s_old = s;
        }
        vTaskDelay(500/portTICK_RATE_MS);
    }
}

void time_task(void *argv)
{
    time_t now;
    struct tm timeinfo;

    time(&now);
    localtime_r(&now, &timeinfo);

    if (timeinfo.tm_year < (2016 - 1900)) {
        ESP_LOGI(TAG, "Time is not set yet. Connecting to WiFi and getting time over NTP.");
    }
    
    setenv("TZ", "CST-8", 1);
    tzset();
    while (1)
    {        
        time(&now);
        localtime_r(&now, &timeinfo);
            
        h = timeinfo.tm_hour;
        m = timeinfo.tm_min;
        s = timeinfo.tm_sec;
        printf("%d/%d/%d ", 1900 + timeinfo.tm_year, timeinfo.tm_mon, timeinfo.tm_mday);
        printf("%d:%d:%d\n", timeinfo.tm_hour, timeinfo.tm_min, timeinfo.tm_sec);

        vTaskDelay(1000/portTICK_RATE_MS);
    }
}

void app_main()
{   
    int ret = 0;

    ESP_LOGI(TAG,"start Gpio_Init");
    Gpio_Init();
    get_system_info();
    
    hl_uart_config_t uart_config;
    uart_config.uart_num = UART_NUM_0;
    uart_config.bate = 74880;

    ESP_LOGI(TAG,"start my_usart_init");
    my_uart_init(uart_config);
    ESP_LOGI(TAG,"create uart_recv_task");
    xTaskCreate(uart_recv_task,"uart_recv_task",1024*2,NULL, 20, NULL);

    my_spi_init(NULL);
    ret = max7219Init(MAX7219_Write_Data, 4);
    if (ret){
        ESP_LOGE(TAG,"max7219Init err");
    }

    ESP_LOGI(TAG,"create refresh task");
    xTaskCreate(refresh_task,"refresh_task",1024*2,NULL, 21, NULL);

    ESP_LOGI(TAG,"create time_task");
    xTaskCreate(time_task,"time_task",1024*2,NULL, 22, NULL);

    ESP_LOGI(TAG,"start run");
}
